
#ifndef _LIST_MODULE_H_
#define _LIST_MODULE_H_

#include <stdio.h>
//#include <stdlib.h>
#include <string.h>

#define LINK_LIST_MAX_LEN				0x4000

#define ARRAY_OBJ_WRAP		1			// FIXME : enable wrap

/******************************************************************
 * fixed table
 ******************************************************************/
template <class t_obj>
class array_obj
{
public:
	array_obj( int max_len = LINK_LIST_MAX_LEN, int wrap = ARRAY_OBJ_WRAP );
	~array_obj(void);

	int					get_max_len(void)				{ return m_max_len; }
	int					get_len(void)					{ return m_len; }
	
	void				wrap_en( int enable )			{ m_wrap = enable; }
	int					wrap_stat(void)					{ return m_wrap; }

	void				free(void);
	int					append( t_obj & data );

	
	int					push_front	( t_obj & data );
	int					push_back	( t_obj & data )	{ return append(data); }

	t_obj *				pop_front	( void );
	t_obj *				pop_back	( void );
	
	t_obj				* get_tail(void);
	t_obj				* get_head(void);

	int 				pop( t_obj & data );
	void				del_head(void);
	t_obj 				& operator[]( int pos );

protected:
	const int			m_max_len;
	t_obj				* m_table;

	int					m_len;
	int					m_head;
	int					m_tail;
	
	int					m_wrap;
};

template <class t_obj>
array_obj<t_obj>::array_obj( int max_len, int wrap ) : m_max_len( max_len ), m_wrap(wrap)
{
	m_table		= new t_obj [m_max_len];

	m_len		= 0;
	m_head		= 0;
	m_tail		= 0;
	
	m_wrap		= 1;
}

template <class t_obj>
array_obj<t_obj>::~array_obj(void)
{
	delete [] m_table;
	m_table		= NULL;
}

template <class t_obj>
void array_obj<t_obj>::free(void)
{
	m_len		= 0;
	m_head		= 0;
	m_tail		= 0;
}

template <class t_obj>
int array_obj<t_obj>::append( t_obj & data )
{
	if( m_len == m_max_len )
	{
		if( m_wrap == 0 )
			return 0;

		m_head++;
		if( m_head == m_max_len )
			m_head	= 0;
	}
	else
	{
		m_len++;
	}

	m_table[m_tail]	= data;
	m_tail++;
	if( m_tail == m_max_len )
		m_tail	= 0;

	return 1;
}

template <class t_obj>
t_obj * array_obj<t_obj>::get_tail(void)
{
	t_obj		* pnode = NULL;

	if( m_len == m_max_len )
	{
		if( m_wrap == 0 )
			return NULL;

		m_head++;
		if( m_head == m_max_len )
			m_head	= 0;
	}
	else
	{
		m_len++;
	}

	pnode	= &m_table[m_tail];
	m_tail++;
	if( m_tail == m_max_len )
		m_tail	= 0;

	return pnode;
}

template <class t_obj>
t_obj * array_obj<t_obj>::get_head(void)
{
	return (m_len == 0) ? NULL : (&m_table[m_head]);
}

template <class t_obj>
int array_obj<t_obj>::pop( t_obj & data )
{
	if( m_len == 0 )
		return 0;

	//
	data	= m_table[m_head];
	m_head++;
	if( m_head == m_max_len )
		m_head	= 0;
	//
	m_len--;

	return 1;
}

template <class t_obj>
void array_obj<t_obj>::del_head(void)
{
	if( m_len == 0 )
		return;

	//
	m_head++;
	if( m_head == m_max_len )
		m_head	= 0;
	//
	m_len--;
}

template <class t_obj>
int array_obj<t_obj>::push_front( t_obj & data )
{
	if( m_len == m_max_len )
	{
		if( m_wrap == 0 )
			return 0;

		if( m_tail == 0 )
			m_tail	= m_max_len - 1;
		else
			m_tail--;

		if( m_head == 0 )
			m_head	= m_max_len - 1;
		else
			m_head--;

		m_table[m_head]	= data;
	}
	else
	{
		if( m_head == 0 )
			m_head	= m_max_len - 1;
		else
			m_head--;

		m_table[m_head]	= data;
		m_len++;
	}

	return 1;
}

template <class t_obj>
t_obj * array_obj<t_obj>::pop_front( void )
{
	if( m_len == 0 )
		return NULL;

	t_obj *		pdata;

	//
	pdata		= &(m_table[m_head]);
	m_head++;
	if( m_head == m_max_len )
		m_head	= 0;
	//
	m_len--;

	return pdata;
}

template <class t_obj>
t_obj * array_obj<t_obj>::pop_back( void )
{
	if( m_len == 0 )
		return NULL;

	t_obj *		pdata;
	int			temp;

	if( m_tail == 0 )
		temp	= m_max_len - 1;
	else
		temp	= m_tail - 1;
	//
	pdata		= &(m_table[temp]);
	m_tail		= temp;
	//
	m_len--;

	return pdata;
}


template <class t_obj>
t_obj & array_obj<t_obj>::operator[]( int pos )
{
	int			num	= m_head + pos;
	if( num >= m_max_len )
		num	-= m_max_len;
	return m_table[num];
}


#endif
